<template>
  <div class="user-list-container">
    <!-- 页面标题 -->
    <h1>用户管理系统</h1>
    
    <!-- 搜索与添加按钮区域：左侧搜索，右侧添加 -->
    <div class="action-bar">
      <div class="action-left">
        <!-- 搜索输入（支持清空） -->
        <a-input
          v-model:value="searchQuery"
          allow-clear
          placeholder="搜索姓名或邮箱"
          style="max-width: 280px"
        />
      </div>
      <div class="action-right">
        <a-button type="primary" @click="showAddModal = true">
          <template #icon><PlusOutlined /></template>
          添加用户
        </a-button>
      </div>
    </div>

    <!-- 用户列表表格 -->
    <!-- 为什么要用a-table？因为它提供了排序、分页、选择等很多内置功能 -->
  <a-table 
      :columns="columns" 
      :data-source="paginatedUsers"
      :loading="loading"
      :pagination="pagination"
      @change="handleTableChange"
      row-key="id"
      class="user-table"
    >
      <!-- 自定义操作列的渲染 -->
      <template #bodyCell="{ column, record, index }">
        <!-- 序号列：显示当前行的序号（从1开始） -->
        <template v-if="column.key === 'seq'">
          {{ getRowSeq(index) }}
        </template>
        <template v-if="column.key === 'action'">
          <a-space>
            <!-- 编辑按钮 -->
            <a-button type="link" size="small" @click="handleEdit(record)">
              编辑
            </a-button>
            <!-- 删除按钮 -->
            <a-popconfirm 
              title="确定要删除这个用户吗？" 
              @confirm="handleDelete(record.id)"
              ok-text="确定"
              cancel-text="取消"
            >
              <a-button type="link" danger size="small">
                删除
              </a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </a-table>

    <!-- 添加用户的模态框 -->
    <!-- 什么是模态框？就是一个弹出窗口，会阻止用户操作页面其他内容 -->
    <a-modal 
      v-model:open="showAddModal" 
      title="添加新用户" 
      @ok="handleAdd"
      @cancel="resetForm"
    >
      <a-form :model="formData" layout="vertical">
        <a-form-item label="姓名" required>
          <a-input v-model:value="formData.name" placeholder="请输入姓名" />
        </a-form-item>
        <a-form-item label="邮箱" required>
          <a-input v-model:value="formData.email" placeholder="请输入邮箱" />
        </a-form-item>
        <a-form-item label="年龄">
          <a-input-number v-model:value="formData.age" :min="1" :max="120" style="width: 100%" />
        </a-form-item>
      </a-form>
    </a-modal>
    
    <!-- 编辑用户的模态框 -->
    <!-- 小白解释：点击“编辑”弹出这个窗口，改完后点确定会保存到数据库 -->
    <a-modal 
      v-model:open="showEditModal" 
      title="编辑用户" 
      @ok="handleEditSubmit" 
      @cancel="resetEditForm"
    >
      <a-form :model="editFormData" layout="vertical">
        <a-form-item label="姓名" required>
          <a-input v-model:value="editFormData.name" placeholder="请输入姓名" />
        </a-form-item>
        <a-form-item label="邮箱" required>
          <a-input v-model:value="editFormData.email" placeholder="请输入邮箱" />
        </a-form-item>
        <a-form-item label="年龄">
          <a-input-number v-model:value="editFormData.age" :min="1" :max="120" style="width: 100%" />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
// 什么是<script setup>？这是Vue3的语法糖，让我们写组件更简单
// lang="ts"表示使用TypeScript，可以让代码更安全，有代码提示

import { ref, onMounted } from 'vue'
// 引入Ant Design Vue的图标组件
import { PlusOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'

// 定义用户数据结构
interface User {
  id: number
  name: string
  email: string
  age: number
  createdAt: string
}

// 表格列配置
// 为什么要定义columns？告诉a-table要显示哪些列，每列的标题、数据字段等
const columns = [
  {
    title: '序号',
    key: 'seq',
    width: 80
  },
  {
    title: 'ID',  // 列标题
    dataIndex: 'id',  // 对应数据中的字段名
    key: 'id',  // 唯一标识
    width: 80,  // 列宽度
    // 开启排序，按数字大小排序
    sorter: (a: User, b: User) => a.id - b.id,
    sortDirections: ['ascend', 'descend']
  },
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    width: 120,
    sorter: (a: User, b: User) => a.name.localeCompare(b.name),
    sortDirections: ['ascend', 'descend']
  },
  {
    title: '邮箱',
    dataIndex: 'email',
    key: 'email',
    sorter: (a: User, b: User) => a.email.localeCompare(b.email),
    sortDirections: ['ascend', 'descend']
  },
  {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
    width: 80,
    sorter: (a: User, b: User) => (a.age ?? 0) - (b.age ?? 0),
    sortDirections: ['ascend', 'descend']
  },
  {
    title: '创建时间',
    dataIndex: 'createdAt',
    key: 'createdAt',
    width: 180,
    sorter: (a: User, b: User) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),
    sortDirections: ['ascend', 'descend']
  },
  {
    title: '操作',
    key: 'action',
    width: 150,
    // 固定右側操作列
    fixed: 'right'
  }
]

// 响应式数据定义
// 计算每行的序号
// 函数作用：根据表格的行索引生成“序号”（从1开始），并考虑当前分页。
// 小白解释：如果在第2页，前面已经有第1页的条目，所以要加上“分页偏移量”。
const getRowSeq = (index: number): number => {
  const offset = (pagination.value.current - 1) * pagination.value.pageSize
  return offset + index + 1
}
 
// ref是什么？Vue的响应式系统，数据变化时界面会自动更新
const users = ref<User[]>([])  // 用户列表数据
const loading = ref(false)  // 加载状态
const showAddModal = ref(false)  // 是否显示添加模态框
const showEditModal = ref(false)  // 是否显示编辑模态框

// 搜索关键词（小白解释：输入姓名或邮箱的关键字即可筛选）
const searchQuery = ref('')

// 表格分页配置（与 a-table 同步）
const pagination = ref({
  current: 1,
  pageSize: 10,
  showSizeChanger: true,
  pageSizeOptions: ['5', '10', '20', '50'],
  total: 0
})

/**
 * 处理表格的分页、排序变化
 * 小白解释：当你切换页码或点列头排序时，会执行这个函数，把最新的页码和每页数量记住。
 */
const handleTableChange = (pag: any) => {
  pagination.value.current = pag.current
  pagination.value.pageSize = pag.pageSize
}

/**
 * 计算：先按搜索关键词过滤，再根据分页只取当前页的数据
 * 小白解释：先把不匹配的记录过滤掉，再只展示这一页需要的几条。
 */
import { computed, watchEffect } from 'vue'
const filteredUsers = computed(() => {
  const q = searchQuery.value.trim().toLowerCase()
  if (!q) return users.value
  return users.value.filter(u => {
    return (
      (u.name && u.name.toLowerCase().includes(q)) ||
      (u.email && u.email.toLowerCase().includes(q))
    )
  })
})

const paginatedUsers = computed(() => {
  const start = (pagination.value.current - 1) * pagination.value.pageSize
  const end = start + pagination.value.pageSize
  return filteredUsers.value.slice(start, end)
})

// 同步总条数到分页对象，让分页器显示正确的页数
watchEffect(() => {
  pagination.value.total = filteredUsers.value.length
})

// 表单数据
const formData = ref({
  name: '',
  email: '',
  age: 18
})

// 后端 API 基地址
// 小白解释：这里就是我们的后端地址，页面通过它去拿数据/新增/删除。
const API_BASE = 'http://localhost:3000'

// 获取用户列表（调用后端）
// 函数作用：向后端发起 GET 请求，拿到真实数据库里的用户列表。
// 为什么这样做？只有用后端的数据，ID 才是数据库的自增 ID，不是临时的时间戳。
const fetchUsers = async () => {
  loading.value = true
  try {
    const resp = await fetch(`${API_BASE}/api/users`)
    const json = await resp.json()
    if (json.success) {
      users.value = json.data.users
    } else {
      message.error(json.message || '获取用户列表失败')
    }
  } catch (err) {
    message.error('获取用户列表失败：后端不可访问或跨域受限')
  } finally {
    loading.value = false
  }
}

// 处理添加用户（接入后端）
// 函数作用：向后端 POST 新用户，后端会返回“真正的自增ID”，再刷新列表。
// 为什么要改？之前用 Date.now() 是临时ID，所以你看到很长的数字，现在改成数据库 ID。
const handleAdd = async () => {
  if (!formData.value.name || !formData.value.email) {
    message.warning('请填写完整信息')
    return
  }
  try {
    const resp = await fetch(`${API_BASE}/api/users`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name: formData.value.name,
        email: formData.value.email,
        age: formData.value.age
      })
    })
    const json = await resp.json()
    if (json.success) {
      message.success('添加用户成功！')
      showAddModal.value = false
      resetForm()
      // 刷新列表，展示后端返回的真实 ID
      await fetchUsers()
    } else {
      message.error(json.message || '添加用户失败')
    }
  } catch (err) {
    message.error('添加用户失败：后端不可访问或跨域受限')
  }
}

// 编辑表单数据
// 小白解释：这里单独准备一个“编辑用”的表单数据，避免和“新增用”的表单混在一起。
const editFormData = ref<{ id: number | null; name: string; email: string; age: number | null }>({
  id: null,
  name: '',
  email: '',
  age: null
})

// 处理编辑用户（打开弹窗并填充数据）
// 函数作用：把当前行用户数据放到“编辑表单”，然后显示编辑弹窗。
// 小白解释：先把数据塞到表单里给你改；真正保存是在下面的 handleEditSubmit。
const handleEdit = (user: User) => {
  editFormData.value = {
    id: user.id,
    name: user.name,
    email: user.email,
    age: user.age ?? null
  }
  showEditModal.value = true
}

// 提交编辑（接入后端 PUT 更新）
// 函数作用：把弹窗里改好的内容发到后端保存，成功后刷新列表。
// 小白解释：点确定就把新数据发给后端，保存成功后重新加载列表。
const handleEditSubmit = async () => {
  if (!editFormData.value.id) {
    message.error('没有要编辑的用户 ID')
    return
  }
  if (!editFormData.value.name || !editFormData.value.email) {
    message.warning('请填写完整信息')
    return
  }
  try {
    const resp = await fetch(`${API_BASE}/api/users/${editFormData.value.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name: editFormData.value.name,
        email: editFormData.value.email,
        age: editFormData.value.age ?? undefined
      })
    })
    const json = await resp.json()
    if (json.success) {
      message.success('编辑保存成功！')
      showEditModal.value = false
      resetEditForm()
      await fetchUsers()
    } else {
      message.error(json.message || '编辑保存失败')
    }
  } catch (err) {
    message.error('编辑保存失败：后端不可访问或跨域受限')
  }
}

// 重置编辑表单
// 函数作用：清空编辑表单，避免上一次数据残留。
const resetEditForm = () => {
  editFormData.value = { id: null, name: '', email: '', age: null }
}

// 处理删除用户（接入后端）
// 函数作用：向后端 DELETE 指定用户，成功后刷新列表。
const handleDelete = async (id: number) => {
  try {
    const resp = await fetch(`${API_BASE}/api/users/${id}`, { method: 'DELETE' })
    const json = await resp.json()
    if (json.success) {
      message.success('删除用户成功！')
      await fetchUsers()
    } else {
      message.error(json.message || '删除用户失败')
    }
  } catch (err) {
    message.error('删除用户失败：后端不可访问或跨域受限')
  }
}

// 重置表单
const resetForm = () => {
  formData.value = {
    name: '',
    email: '',
    age: 18
  }
}

// 组件挂载完成后执行
// 什么是onMounted？Vue的生命周期钩子，组件创建完成后会自动调用
onMounted(() => {
  fetchUsers()
})
</script>

<style scoped>
/* scoped是什么意思？样式只作用于当前组件，不会影响其他组件 */

.user-list-container {
  padding: 24px;  /* 内边距 */
  background-color: #fff;  /* 白色背景 */
  min-height: 100vh;  /* 最小高度为视口高度 */
}

.action-bar {
  margin-bottom: 16px;  /* 下边距 */
  display: flex;  /* 弹性布局 */
  justify-content: space-between;  /* 左右分布：左边搜索，右边按钮 */
  align-items: center;
}

.action-left { flex: 1; }
.action-right { margin-left: 12px; }

.user-table {
  margin-top: 16px;  /* 上边距 */
}

/* 响应式设计：屏幕宽度小于768px时的样式 */
@media (max-width: 768px) {
  .user-list-container {
    padding: 16px;  /* 减小内边距 */
  }
  
  .action-bar {
    justify-content: center;  /* 按钮居中 */
  }
}
</style>